/**
 * Software License, Version 1.0
 * 
 * Copyright 2008 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgment:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgment may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or Granules, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called Granules, 
 * nor may Indiana University or Community Grids Lab or Granules appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 * LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 * WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 * NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 * INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 * INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 * "VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 * LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 * ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 * GENERATED USING SOFTWARE.
 */
package cgl.granules.results;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;

import cgl.granules.exception.MarshallingException;

/**
 * This is a utility class which can be used for marshalling and unmarshalling
 * some of the most commonly used result primitives.
 * 
 * @author Shrideep Pallickara
 * 
 */
public class ResultPayload {

	public static final int INT = 1;
	public static final int SHORT = 2;
	public static final int LONG = 3;
	public static final int DOUBLE = 4;
	public static final int FLOAT = 5;
	public static final int STRING = 7;
	public static final int OBJECT = 8;
	public static final int HASHTABLE = 9;
	public static final int INT_ARRAY = 11;
	public static final int SHORT_ARRAY = 12;
	public static final int LONG_ARRAY = 13;
	public static final int DOUBLE_ARRAY = 14;
	public static final int FLOAT_ARRAY = 15;
	public static final int STRING_ARRAY = 16;
	public static final int OBJECT_ARRAY = 17;
	public static final int INT_2D_ARRAY = 18;
	public static final int SHORT_2D_ARRAY = 19;
	public static final int LONG_2D_ARRAY = 20;
	public static final int DOUBLE_2D_ARRAY = 21;
	public static final int FLOAT_2D_ARRAY = 22;
	public static final int STRING_2D_ARRAY = 23;
	public static final int OBJECT_2D_ARRAY = 24;

	private static final ResultPayload instance = new ResultPayload();

	private ResultPayload() {
	}

	/**
	 * Retrieve the payload instance
	 * 
	 * @return singleton instance of the ResultPayload.
	 */
	public static ResultPayload getInstance() {
		return instance;
	}

	/**
	 * This method converts an <code>int</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>int</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>int</code>.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>int</code>.
	 */
	public byte[] getBytes(int value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		try {
			dout.writeInt(value);
			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling int. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into an <code>int</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the <code>int</code>
	 *            .
	 * @return The <code>int</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>int</code>.
	 */
	public int getInt(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int value = din.readInt();

			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling int. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a <code>short</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>short</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>short</code>.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>short</code>.
	 */
	public byte[] getBytes(short value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		try {
			dout.writeShort(value);
			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling the short. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>short</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the
	 *            <code>short</code> .
	 * @return The <code>short</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>short</code>.
	 */
	public short getShort(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			short value = din.readShort();

			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling short. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a <code>long</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>long</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>long</code>.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>long</code>.
	 */
	public byte[] getBytes(long value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		try {
			dout.writeLong(value);
			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling the long. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>long</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the
	 *            <code>long</code> .
	 * @return The <code>long</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>long</code>.
	 */
	public long getLong(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			long value = din.readLong();

			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling long. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a <code>double</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>double</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>double</code>.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>double</code>.
	 */
	public byte[] getBytes(double value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		try {
			dout.writeDouble(value);
			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling the double. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>double</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the
	 *            <code>double</code> .
	 * @return The <code>double</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>double</code>.
	 */
	public double getDouble(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			double value = din.readDouble();

			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling double. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a <code>float</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>float</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>float</code>.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>float</code>.
	 */
	public byte[] getBytes(float value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		try {
			dout.writeFloat(value);
			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling the float. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>float</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the
	 *            <code>float</code> .
	 * @return The <code>float</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>float</code>.
	 */
	public float getFloat(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			float value = din.readFloat();
			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling float. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a <code>String</code> into a <code>byte[]</code>.
	 * 
	 * @param value
	 *            The <code>String</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>String</code>.
	 * @throws NullPointerException
	 *             If the specified <code>String</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the <code>String</code>.
	 */
	public byte[] getBytes(String value) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (value == null) {
			throw new NullPointerException("Specified String is null.");
		}

		try {
			byte[] valueBytes = value.getBytes();
			int valueLength = valueBytes.length;

			dout.writeInt(valueLength);
			dout.write(valueBytes);

			dout.flush();

			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling the String. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>String</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> representation of the
	 *            <code>String</code> .
	 * @return The <code>String</code> representation of the <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified <code>byte[]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the <code>String</code>.
	 */
	public String getString(byte[] marshalledBytes) throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			byte[] valueBytes = new byte[din.readInt()];
			din.readFully(valueBytes);

			String value = new String(valueBytes);
			return value;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling String. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts an int[] into a byte[].
	 * 
	 * @param sequence
	 *            The int[] to be marshalled into byte[].
	 * @return byte[] representation of the int[]
	 * @throws NullPointerException
	 *             If the specified int[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the int[].
	 */
	public byte[] getBytes(int[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified int[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeInt(sequence[i]);
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
			
			baOutputStream.close();
			dout.close();
			
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling int[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into an int[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into an int[].
	 * @return The int[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the int[].
	 */
	public int[] getIntArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			int[] sequence = new int[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				sequence[i] = din.readInt();
			}
			baInputStream.close();
			din.close();
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling int[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a short[] into a byte[].
	 * 
	 * @param sequence
	 *            The short[] to be marshalled into a byte[].
	 * @return byte[] representation of the short[]
	 * @throws NullPointerException
	 *             If the specified short[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the short[].
	 */
	public byte[] getBytes(short[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified long[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeShort(sequence[i]);
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling short[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a short[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a short[].
	 * @return The short[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the short[].
	 */
	public short[] getShortArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			short[] sequence = new short[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				sequence[i] = din.readShort();
			}
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling short[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a long[] into a byte[].
	 * 
	 * @param sequence
	 *            The long[] to be marshalled into a byte[].
	 * @return byte[] representation of the long[]
	 * @throws NullPointerException
	 *             If the specified long[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the long[].
	 */
	public byte[] getBytes(long[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified long[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeLong(sequence[i]);
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
			baOutputStream.close();
			dout.close();
			
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling long[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a long[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a long[].
	 * @return The long[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the long[].
	 */
	public long[] getLongArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			long[] sequence = new long[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				sequence[i] = din.readLong();
			}
			
			baInputStream.close();
			din.close();
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling long[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a double[] into a byte[].
	 * 
	 * @param sequence
	 *            The double[] to be marshalled into a byte[].
	 * @return byte[] representation of the double[]
	 * @throws NullPointerException
	 *             If the specified double[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the double[].
	 */
	public byte[] getBytes(double[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified double[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeDouble(sequence[i]);
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling double[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a double[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a double[].
	 * @return The double[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the double[].
	 */
	public double[] getDoubleArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			double[] sequence = new double[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				sequence[i] = din.readDouble();
			}
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling double[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a float[] into a byte[].
	 * 
	 * @param sequence
	 *            The float[] to be marshalled into a byte[].
	 * @return byte[] representation of the float[]
	 * @throws NullPointerException
	 *             If the specified long[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the float[].
	 */
	public byte[] getBytes(float[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified float[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeFloat(sequence[i]);
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a float[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a float[].
	 * @return The float[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unmarshalling the float[].
	 */
	public float[] getFloatArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			float[] sequence = new float[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				sequence[i] = din.readFloat();
			}
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling float[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a String[] into a byte[].
	 * 
	 * @param sequence
	 *            The String[] to be marshalled into a byte[].
	 * @return byte[] representation of the String[]
	 * @throws NullPointerException
	 *             If the specified long[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the String[].
	 */
	public byte[] getBytes(String[] sequence) throws MarshallingException {
		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		if (sequence == null) {
			throw new NullPointerException("Specified String[] is null.");
		}

		int numOfElements = sequence.length;
		try {
			dout.writeInt(numOfElements);
			for (int i = 0; i < numOfElements; i++) {
				dout.writeInt(sequence[i].length());
				dout.write(sequence[i].getBytes());
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling String[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a String[].
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a String[].
	 * @return The String[] representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems Unarshalling the String[].
	 */
	public String[] getStringArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}
		try {
			int numOfElements = din.readInt();
			String[] sequence = new String[numOfElements];

			for (int i = 0; i < numOfElements; i++) {
				byte[] stringBytes = new byte[din.readInt()];
				din.read(stringBytes);
				sequence[i] = new String(stringBytes);
			}
			return sequence;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling String[]. "
					+ ioe.getMessage());
		}
	}

	/**
	 * This method converts a Hashtable into a byte[].
	 * 
	 * @param sequence
	 *            The Hashtable to be marshalled into a byte[].
	 * @return byte[] representation of the Hashtable
	 * @throws NullPointerException
	 *             If the specified hashtable is NULL.
	 * @throws MarshallingException
	 *             If there are problems Marshalling the hashtable.
	 */
	public byte[] getBytes(Hashtable sequence) throws MarshallingException {
		if (sequence == null) {
			throw new NullPointerException("Specified Hashtable is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();

		try {
			ObjectOutputStream dout = new ObjectOutputStream(
					new BufferedOutputStream(baOutputStream));

			dout.writeObject(sequence);
			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling Hashtable. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a byte[] into a Hashtable.
	 * 
	 * @param marshalledBytes
	 *            The byte[] that needs to be unmarshalled into a Hashtable.
	 * @return The Hashtable representation of the byte[]
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the Hashtable.
	 */
	public Hashtable getHashtable(byte[] marshalledBytes)
			throws MarshallingException {
		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);

		try {
			ObjectInputStream din = new ObjectInputStream(
					new BufferedInputStream(baInputStream));
			Object object = din.readObject();
			Hashtable<Object, Object> hashObject = (Hashtable<Object, Object>) object;
			return hashObject;

		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling Hashtable."
					+ ioe.getMessage());
		} catch (ClassNotFoundException e) {
			throw new MarshallingException("Problems un-marshalling Hashtable."
					+ e.getMessage());
		}
	}

	/**
	 * This method converts a <code>int[][]</code> into a <code>byte[]</code>.
	 * 
	 * @param matrix
	 *            The <code>int[][]</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>int[][]</code>
	 * @throws NullPointerException
	 *             If the specified <code>int[][]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems marshalling the <code>int[][]</code>.
	 */
	public byte[] getBytes(int[][] matrix) throws MarshallingException {
		if (matrix == null) {
			throw new NullPointerException("Specified matrix is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		int numOfRows = matrix.length;
		try {
			dout.writeInt(numOfRows);
			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = matrix[i].length;
				dout.writeInt(numOfColumnsInRow);
				for (int j = 0; j < numOfColumnsInRow; j++) {
					dout.writeInt(matrix[i][j]);
				}
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>int[][]</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> that needs to be unmarshalled into a
	 *            <code>int[][]</code>.
	 * @return The <code>int[][]</code> representation of the
	 *         <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the <code>int[][]</code>.
	 */
	public int[][] getInt2DArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		try {
			int numOfRows = din.readInt();
			int[][] matrix = new int[numOfRows][];

			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = din.readInt();
				matrix[i] = new int[numOfColumnsInRow];
				for (int j = 0; j < numOfColumnsInRow; j++) {
					matrix[i][j] = din.readInt();
				}
			}

			return matrix;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling int[][]. "
					+ ioe.getMessage());
		}
	}

	
	/**
	 * This method converts a <code>short[][]</code> into a <code>byte[]</code>.
	 * 
	 * @param matrix
	 *            The <code>short[][]</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>short[][]</code>
	 * @throws NullPointerException
	 *             If the specified <code>short[][]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems marshalling the <code>short[][]</code>.
	 */
	public byte[] getBytes(short[][] matrix) throws MarshallingException {
		if (matrix == null) {
			throw new NullPointerException("Specified matrix is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		int numOfRows = matrix.length;
		try {
			dout.writeInt(numOfRows);
			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = matrix[i].length;
				dout.writeInt(numOfColumnsInRow);
				for (int j = 0; j < numOfColumnsInRow; j++) {
					dout.writeShort(matrix[i][j]);
				}
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>short[][]</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> that needs to be unmarshalled into a
	 *            <code>short[][]</code>.
	 * @return The <code>short[][]</code> representation of the
	 *         <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the <code>short[][]</code>.
	 */
	public short[][] getShort2DArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		try {
			int numOfRows = din.readInt();
			short[][] matrix = new short[numOfRows][];

			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = din.readInt();
				matrix[i] = new short[numOfColumnsInRow];
				for (int j = 0; j < numOfColumnsInRow; j++) {
					matrix[i][j] = din.readShort();
				}
			}

			return matrix;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling short[][]. "
					+ ioe.getMessage());
		}
	}
	
	
	
	
	
	
	/**
	 * This method converts a <code>long[][]</code> into a <code>byte[]</code>.
	 * 
	 * @param matrix
	 *            The <code>long[][]</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>long[][]</code>
	 * @throws NullPointerException
	 *             If the specified <code>long[][]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems marshalling the <code>long[][]</code>.
	 */
	public byte[] getBytes(long[][] matrix) throws MarshallingException {
		if (matrix == null) {
			throw new NullPointerException("Specified matrix is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		int numOfRows = matrix.length;
		try {
			dout.writeInt(numOfRows);
			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = matrix[i].length;
				dout.writeInt(numOfColumnsInRow);
				for (int j = 0; j < numOfColumnsInRow; j++) {
					dout.writeLong(matrix[i][j]);
				}
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>long[][]</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> that needs to be unmarshalled into a
	 *            <code>long[][]</code>.
	 * @return The <code>long[][]</code> representation of the
	 *         <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the <code>long[][]</code>.
	 */
	public long[][] getLong2DArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		try {
			int numOfRows = din.readInt();
			long[][] matrix = new long[numOfRows][];

			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = din.readInt();
				matrix[i] = new long[numOfColumnsInRow];
				for (int j = 0; j < numOfColumnsInRow; j++) {
					matrix[i][j] = din.readLong();
				}
			}

			return matrix;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling long[][]. "
					+ ioe.getMessage());
		}
	}
	
	
	
	
	
	/**
	 * This method converts a <code>double[][]</code> into a <code>byte[]</code>.
	 * 
	 * @param matrix
	 *            The <code>double[][]</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>double[][]</code>
	 * @throws NullPointerException
	 *             If the specified <code>double[][]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems marshalling the <code>double[][]</code>.
	 */
	public byte[] getBytes(double[][] matrix) throws MarshallingException {
		if (matrix == null) {
			throw new NullPointerException("Specified matrix is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		int numOfRows = matrix.length;
		try {
			dout.writeInt(numOfRows);
			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = matrix[i].length;
				dout.writeInt(numOfColumnsInRow);
				for (int j = 0; j < numOfColumnsInRow; j++) {
					dout.writeDouble(matrix[i][j]);
				}
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>double[][]</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> that needs to be unmarshalled into a
	 *            <code>double[][]</code>.
	 * @return The <code>double[][]</code> representation of the
	 *         <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the <code>double[][]</code>.
	 */
	public double[][] getDouble2DArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		try {
			int numOfRows = din.readInt();
			double[][] matrix = new double[numOfRows][];

			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = din.readInt();
				matrix[i] = new double[numOfColumnsInRow];
				for (int j = 0; j < numOfColumnsInRow; j++) {
					matrix[i][j] = din.readDouble();
				}
			}

			return matrix;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling double[][]. "
					+ ioe.getMessage());
		}
	}
	
	
	
	
	/**
	 * This method converts a <code>float[][]</code> into a <code>byte[]</code>.
	 * 
	 * @param matrix
	 *            The <code>float[][]</code> to be marshalled into a
	 *            <code>byte[]</code>.
	 * @return <code>byte[]</code> representation of the <code>float[][]</code>
	 * @throws NullPointerException
	 *             If the specified <code>float[][]</code> is NULL.
	 * @throws MarshallingException
	 *             If there are problems marshalling the <code>float[][]</code>.
	 */
	public byte[] getBytes(float[][] matrix) throws MarshallingException {
		if (matrix == null) {
			throw new NullPointerException("Specified matrix is null.");
		}

		byte[] marshalledBytes = null;
		ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(
				baOutputStream));

		int numOfRows = matrix.length;
		try {
			dout.writeInt(numOfRows);
			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = matrix[i].length;
				dout.writeInt(numOfColumnsInRow);
				for (int j = 0; j < numOfColumnsInRow; j++) {
					dout.writeFloat(matrix[i][j]);
				}
			}

			dout.flush();
			marshalledBytes = baOutputStream.toByteArray();
		} catch (IOException ioe) {
			throw new MarshallingException("Problems marshalling float[]. "
					+ ioe.getMessage());
		}
		return marshalledBytes;
	}

	/**
	 * This method converts a <code>byte[]</code> into a <code>float[][]</code>.
	 * 
	 * @param marshalledBytes
	 *            The <code>byte[]</code> that needs to be unmarshalled into a
	 *            <code>float[][]</code>.
	 * @return The <code>float[][]</code> representation of the
	 *         <code>byte[]</code>
	 * @throws NullPointerException
	 *             If the specified byte[] is NULL.
	 * @throws MarshallingException
	 *             If there are problems unmarshalling the <code>float[][]</code>.
	 */
	public float[][] getFloat2DArray(byte[] marshalledBytes)
			throws MarshallingException {
		ByteArrayInputStream baInputStream = new ByteArrayInputStream(
				marshalledBytes);
		DataInputStream din = new DataInputStream(new BufferedInputStream(
				baInputStream));

		if (marshalledBytes == null) {
			throw new NullPointerException("Specified byte[] is null.");
		}

		try {
			int numOfRows = din.readInt();
			float[][] matrix = new float[numOfRows][];

			for (int i = 0; i < numOfRows; i++) {
				int numOfColumnsInRow = din.readInt();
				matrix[i] = new float[numOfColumnsInRow];
				for (int j = 0; j < numOfColumnsInRow; j++) {
					matrix[i][j] = din.readFloat();
				}
			}

			return matrix;
		} catch (IOException ioe) {
			throw new MarshallingException("Problems un-marshalling float[][]. "
					+ ioe.getMessage());
		}
	}
}
